#ifndef GDT_H_
#define GDT_H_

#include <types.h>

#define SEL_NULL 0x00
#define SEL_CODE 0x08
#define SEL_DATA 0x10

#define GDT_ACCESS ((1 << 4) | (1 << 7))
#define GDT_ACCESS_RING0 (0 << 5)
#define GDT_ACCESS_RING1 (1 << 5)
#define GDT_ACCESS_RING2 (2 << 5)
#define GDT_ACCESS_RING3 (3 << 5)
#define GDT_ACCESS_EXEC (1 << 3)
#define GDT_ACCESS_DATA (0 << 3)
#define GDT_ACCESS_UP (0 << 2)
#define GDT_ACCESS_DOWN (1 << 2)
#define GDT_ACCESS_NORW (0 << 1)
#define GDT_ACCESS_RW (1 << 1)

#define GDT_FLAGS_BYTE (0 << 7)
#define GDT_FLAGS_4K (1 << 7)
#define GDT_FLAGS_16BIT (0 << 6)
#define GDT_FLAGS_32BIT (1 << 6)

typedef struct gdt_entry
{
    word limit_low;
    word base_low;
    byte base_middle;
    byte access;
    byte flags;
    byte base_high;
} __attribute__((packed)) gdt_entry_t;

typedef struct gdt_ptr
{
    word limit;
    dword base;
} __attribute__((packed)) gdt_ptr_t;

void init_gdt(void);
void gdt_set_entry(int index, dword base, dword limit, 
 byte access, byte flags);
void gdt_install(void);
extern void __gdt_install(void);

#endif /*GDT_H_*/
